home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / server / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-21  |  29.3 KB  |  1,036 lines

  1.     /*********************************************************************\
  2.     *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  3.     *                                                                     *
  4.     *  You may copy or modify this file in any manner you wish, provided  *
  5.     *  that this notice is always included, and that you hold the author  *
  6.     *  harmless for any loss or damage resulting from the installation or *
  7.     *  use of this software.                                              *
  8.     \*********************************************************************/
  9.  
  10. #include "tweak.h"
  11. #include "server_def.h"
  12. #include "s_extern.h"
  13.  
  14. #ifdef VMS
  15. #define MOREDOTS         /* remove this if you don't want more than 1 dot
  16.                              in a filename */
  17. /* Use UNIX emulation functions */
  18. #define O_CREAT 0x0200
  19. #define fopen vms_fopen
  20. #define open vms_open
  21. #define access vms_access
  22. #define FSP_STAT vms_stat
  23. #define link rename
  24. int dchanged=0;   /* flag which shows if .fsp_content needs to be updated */
  25. int isvar=0;      /* flag: file is in variable record format */
  26. #else
  27. #define FSP_STAT stat
  28. #endif
  29.  
  30. FPCACHE *cache_p, fpcache[FSP_FILE_CACHE+1]; /* file cache */
  31.  
  32. extern char *readme_file;
  33.  
  34. /*****************************************************************************
  35. * This is a modified server_file that hashes file names.             *
  36. *****************************************************************************/
  37.  
  38. #define NBSIZE (2*sizeof(UBUF))
  39.  
  40. #define fexist(A) (!access(A,0))
  41. #define touch(A) close(open(A,O_CREAT,0777))
  42. #define LF_PFX '&'
  43. #define LP_PFX '\\'
  44.  
  45. static int server_check_pass PROTO2(char *, ownerfile, char *, password)
  46. {
  47.   FILE *fp;
  48.   char fsp_passwd[80];
  49.   
  50.   if(dbug) printf("check_pass: opening file %s\n", ownerfile);
  51.   fp = fopen(ownerfile, "r");
  52.   if(fscanf(fp, "%s", fsp_passwd) != 1) {
  53.     if(dbug) printf("check_pass: no password in ownerfile\n");
  54.     fclose(fp);
  55.     return 0;
  56.   }
  57.   fclose(fp);
  58.   if(dbug)
  59.     printf("Check_pass: read %s, check with %s\n", fsp_passwd,
  60.        password);
  61.   return strcmp(fsp_passwd, password);
  62. }
  63.  
  64. /*****************************************************************************
  65.  * Routine to check a path string given by the client.
  66.  * Will replace null string by ".".
  67.  * In case of error, returns the error string.
  68.  *****************************************************************************/
  69.  
  70. /*****************************************************************************
  71.  *  The PPATH structure is filled in by the function check_path when given a
  72.  *  path string.  The elements are filled in as such:
  73.  * 
  74.  *    fullp      pointer to a string containing the full path name
  75.  *    f_ptr      pointer to begining of the last component of the path
  76.  *       f_len      length of the last component of the path
  77.  *    d_ptr      pointer to begining of the directory part of path
  78.  *       d_len      length of the directory part of the path
  79.  *
  80.  *  fullp is a null-terminated full path string.
  81.  *  f_ptr is always a null-terminated sub-string of fullp.
  82.  *  p_ptr is generally not null-terminated.
  83.  *****************************************************************************/
  84.  
  85. char *check_path PROTO3(char *, fullp, int, len, PPATH *, pp)
  86. {
  87.   char *s;
  88.   int state;
  89.   
  90.   if(len < 1) return("Path must have non-zero length");
  91.   if(fullp[len-1]) return("Path not null terminated");
  92.   
  93.   pp->d_ptr = "."; pp->d_len = 1;    /* initial dir part ---> root */
  94.   pp->passwd = "\0";            /* default, no password */
  95.   
  96.   if(len == 1 && fullp[0] == 0)    { /* null path --> root */
  97.     pp->fullp = pp->f_ptr = ".";
  98.     pp->f_len = 1;
  99.     return(NULLP);
  100.   }
  101.   
  102.   for(s = pp->fullp = pp->f_ptr = fullp, state = 0; *s; s++) {
  103.     if(*s == '\n') {
  104.       pp->passwd = s+1; *s = '\0';
  105.       if(dbug) printf("check_path: found password field %s\n", s+1);
  106.     }
  107.     else if(*s <= ' ' || *s >= '~') return("Path contains illegal chars");
  108.       
  109.     switch(*s) {
  110.       case LF_PFX:
  111.       case LP_PFX:
  112.       case '.':
  113.         if(!state) return("Path can't begin with '.'");
  114. #ifdef MOREDOTS
  115.     else *s='$'; /* convert dots to '$' */
  116. #endif
  117.     break;
  118.       
  119.       case '/': if(!state) return("Path can't contain '//'");
  120.     pp->d_ptr = fullp;
  121.     pp->d_len = s - fullp;
  122.     pp->f_ptr = s+1;
  123.     state = 0;
  124.     break;
  125.       
  126.       default:
  127.     state = 1;
  128.     break;
  129.     }
  130.   }
  131.   
  132.   pp->f_len = s - pp->f_ptr;
  133.   return(NULLP);
  134. }
  135.  
  136. /*****************************************************************************
  137.  * Put the directory part of the path pp into dbuf.
  138.  * return pointer to the null character.
  139.  *****************************************************************************/
  140.  
  141. static char *copy_dir PROTO2(char *, dbuf, PPATH *, pp)
  142. {
  143.   char *p1,*p2;
  144.   int cnt;
  145.   
  146.   for(p1 = dbuf, p2 = pp->d_ptr, cnt = pp->d_len; cnt--; *p1++ = *p2++);
  147.   *p1 = 0; return(p1);
  148. }
  149.  
  150. /*****************************************************************************
  151.  * Reads directory and write directory listing file.
  152.  *****************************************************************************/
  153.  
  154. static build_dir_file PROTO1(FILE *, fp)
  155. {
  156.   int nlen, skip, rem;
  157.   DIR *dir_f;
  158. #ifdef HAVE_STRUCT_DIRENT
  159.   struct dirent *dp;
  160. #else
  161.   struct direct *dp;
  162. #endif
  163.   struct stat    sb;
  164.   register char  *s;
  165.   RDIRENT rdb;
  166.   static char marker[] = "******************";
  167.   char longname[UBUF_SPACE];
  168.   FILE *lfp;
  169. #ifdef VMS
  170.   char *ext;         /* pointer to strip .dir extension */
  171. #endif
  172.   
  173.   if(!(dir_f = opendir(".")))  { /* assume I have cd to path already */
  174.     fprintf(stderr,"Can't open dir during initialization\n");
  175.     exit(1);
  176.   }
  177.   
  178. #ifdef VMS
  179.   /* VMS doesn't display the current directory as a dot in the list 
  180.    * so create a dummy dotfile (maybe this should be included in the
  181.    * readdir() emulation function) */
  182.   
  183.   rem = UBUF_SPACE;
  184.   nlen = 2;
  185.   rdb.type = RDTYPE_DIR;
  186.   rdb.size = htonl(1024);
  187.   rdb.time = htonl(time((time_t *)0)); /* get current time for curr. dir */
  188.   fwrite(&rdb,1,RDHSIZE,fp);
  189.   fwrite(".",1,nlen,fp);
  190.   
  191.   rem -= (nlen + RDHSIZE);
  192.   
  193.   if((skip = (nlen + RDHSIZE) & 0x3)) {
  194.     fwrite(&rdb,1,4-skip,fp);
  195.     rem -= (4-skip);
  196.   }
  197.   
  198.   /* now collect the files in the directory */
  199.   for( 1 ; dp = readdir(dir_f); ) {
  200.     ext = dp->d_name;
  201.     while (*ext=tolower(*ext)) ext++; /* kludge to convert filename to
  202.                      lowercase */
  203.     s = dp->d_name;
  204.     if (*(ext = s+strlen(s)-1) == '.') *ext=0; /* strip last dot */
  205. #else
  206. #ifdef HAVE_STRUCT_DIRENT
  207.   for(rem = UBUF_SPACE; dp = (struct dirent *)readdir(dir_f); ) {
  208. #else
  209.   for(rem = UBUF_SPACE; dp = (struct direct *)readdir(dir_f); ) {
  210. #endif
  211.     if (dp->d_ino == 0) continue;
  212. #endif
  213.     s = dp->d_name;
  214.       
  215.     if(s[0] == LF_PFX)  {
  216.       s[0] = LP_PFX;
  217.       if(!(lfp = fopen(s,"r"))) {
  218.     unlink(s);
  219.     *s = LF_PFX;
  220.     unlink(s);
  221.     continue;
  222.       }
  223.       fgets(longname,UBUF_SPACE,lfp);  fclose(lfp);
  224.       s[0] = LF_PFX; s = longname; longname[UBUF_SPACE-1] = 0;
  225.     }
  226.       
  227.     if(s[0] == LP_PFX) continue;
  228.       
  229.     /* hide dot files */
  230.     if((s[0]=='.') && ((s[1]!=0) && (s[1] != '.' || s[2] != 0))) continue;
  231.       
  232.     if(stat(dp->d_name,&sb)) continue;
  233.       
  234. #ifdef VMS  /* strip .DIR extension */
  235.     if (sb.st_mode & S_IFDIR) if (ext=strstr(s,".dir")) *ext=0;
  236. # ifdef MOREDOTS /* replace '$' with dots */
  237.     while (s=strstr(s,"$")) *s++='.'; s=dp->d_name;
  238. # endif
  239. #endif /* VMS */
  240.       
  241.     nlen = strlen(s)+1;
  242.       
  243.     if(rem < RDHSIZE + nlen) {
  244.       rdb.type = RDTYPE_SKIP;
  245.       if(rem <= RDHSIZE) { fwrite(marker,1,rem    ,fp); }
  246.       else {
  247.     fwrite(marker,1,RDHSIZE,fp);
  248.     fwrite(s, 1,rem-RDHSIZE,fp);
  249.       }
  250.       rem = UBUF_SPACE;
  251.     }
  252.       
  253.     rdb.type = ((S_IFDIR & sb.st_mode)) ? RDTYPE_DIR : RDTYPE_FILE;
  254.     BB_WRITE4(rdb.bb_size,sb.st_size );
  255.     BB_WRITE4(rdb.bb_time,sb.st_mtime);
  256.       
  257.     fwrite((char *) &rdb,1,RDHSIZE,fp);
  258.     fwrite(s,1,nlen,fp);
  259.     rem -= (nlen + RDHSIZE);
  260.       
  261.     if((skip = (nlen + RDHSIZE) & 0x3)) {
  262.       fwrite((char *) &rdb,1,4-skip,fp);
  263.       rem -= (4-skip);
  264.     }
  265.       
  266.     if(!rem) rem = UBUF_SPACE;
  267.   }
  268.       
  269.   rdb.type = RDTYPE_END;
  270.   fwrite((char *) &rdb,1,RDHSIZE,fp);
  271.     
  272.   fflush(fp);
  273.   closedir(dir_f);
  274. }
  275.   
  276. /***************************************************************************/
  277.   
  278. #ifdef VMS
  279.   /* the problem on VMS-systems is, that the directory-date doesn't change
  280.    * when anything is changed in it, so we need a manual update of the
  281.    * .FSP_CONTENT file after a upload,deletion,etc.
  282.    */
  283. static char *server_update_dir PROTO2(PPATH *, pp, unsigned long, inet_num)
  284. {
  285.   FILE *fp;  /* dummy file, for server_get_dir() */
  286.   char pathname[NBSIZE],*oldpath, *errmsg = "\0";
  287.     
  288.   dchanged=1; /* mark that fsp_content has been changed */
  289.   copy_dir(pathname,pp); /* strip filename from path. */
  290.   oldpath=pp->fullp;pp->fullp=pathname; /* new path, backup old one */
  291.   if(!(errmsg=server_get_dir(pp,inet_num,&fp)))
  292.     fclose(fp); /* update .FSP_CONTENT */
  293.   pp->fullp=oldpath;  /* restore old path */
  294.   return(errmsg);
  295. }
  296. #endif /* VMS */
  297.   
  298. /***************************************************************************/
  299.  
  300. static char *server_get_dir_2 PROTO3(PPATH *, pp, FILE **, fp,
  301.                      struct stat *, sd)
  302. {
  303.   struct stat sf;
  304.   char name_p[NBSIZE], list_p[NBSIZE], tmp[UBUF_SPACE];
  305.   unsigned int hash, i, mask, new_namefile;
  306.   unsigned char *p;
  307.   FILE *np;
  308. #ifdef VMS
  309.   char pathname[NBSIZE];  /* for conversion of pp->fullp */
  310. #endif
  311.     
  312.   mask = dir_cache_limit << 8;
  313.     
  314.   for(hash = 0, p = (unsigned char *) pp->fullp; *p; p++) {
  315.     hash = (hash << 1) ^ *p;
  316.     if(hash & mask) hash ^= (mask+1);
  317.   }
  318.     
  319.   for(i = 8; i--; ) {
  320.     hash <<= 1;
  321.     if(hash & mask) hash ^= (mask+1);
  322.   }
  323.     
  324.   hash = (hash >> 8) & (mask-1);
  325.     
  326. #ifdef VMS   /* dir_cache_dir is already in VMS format */
  327.   sprintf(name_p,"%s.N%x",dir_cache_dir,hash);
  328.   sprintf(list_p,"%s.L%x",dir_cache_dir,hash);
  329. #else
  330.   sprintf(name_p,"%s/.N%x",dir_cache_dir,hash);
  331.   sprintf(list_p,"%s/.L%x",dir_cache_dir,hash);
  332. #endif
  333.     
  334.   if(!(np = fopen(name_p,"r"))) new_namefile = 1;
  335.   else {
  336.     fgets(tmp,UBUF_SPACE,np); fclose(np);
  337.     
  338.     if(strcmp(tmp,pp->fullp)) new_namefile = 1; 
  339. else {
  340. #ifdef VMS
  341.       if(!FSP_STAT(list_p,&sf) && (!dchanged)) {
  342.     /* VMS doesn't change the modification-date of a directory
  343.        when the contents has been changed */
  344. #else
  345.       if(!FSP_STAT(list_p,&sf) && (sf.st_mtime >= sd->st_mtime)) {
  346. #endif
  347.     *fp = fopen(list_p,"r");
  348.     if(!*fp) return("Can't read directory listing");
  349.     return((char *)0);
  350.       }
  351.       new_namefile = 0;
  352.     }
  353.   }
  354.     
  355.   if(new_namefile) {
  356.     if(!(np = fopen(name_p,"w")))
  357.       return("Can't write directory listing name file");
  358.     fputs(pp->fullp,np); fclose(np);
  359.   }
  360. #ifdef VMS
  361.   unlink(list_p); /* erase old list first */
  362. #endif
  363.     
  364.   if(!(*fp = fopen(list_p,"w+"))) 
  365. {
  366. return("directory unreadable");
  367. }
  368.   if(chdir(pp->fullp)) return("Can't cd to directory");
  369.   build_dir_file(*fp);
  370.   if(chdir(home_dir) == -1) {
  371.     perror("chdir2");
  372.     exit(1);
  373.   }
  374. #ifdef VMS
  375.   dchanged=0; /* .fsp_content now up to date */
  376. #endif
  377.   return(NULLP);
  378. }
  379.  
  380. char *server_get_dir PROTO3(PPATH *, pp, unsigned long, inet_num, FILE **, fp)
  381. {
  382.   struct stat sd, sf;
  383.   char   list_p[NBSIZE],owner_p[NBSIZE],private_p[NBSIZE];
  384.   int    fsp_content_exists;
  385. #ifdef VMS
  386.   char dirname[NBSIZE];
  387.     
  388.   /* now the stupid dirname conversion for stat(), I have to look for a
  389.    * unix-like stat() for VMS.
  390.    * I can't make the conversion in stat(), because I don't know
  391.    * when a path is a full-dir or a dir with a filename on the end.
  392.    */
  393.     
  394.   if (*pp->fullp=='.') getcwd(dirname,512,0);
  395.   else strcpy(dirname,pp->fullp);
  396.   strcat(dirname,".dir.1"); /* for here, add .DIR.1 for directory */
  397.   
  398.   if(FSP_STAT(dirname,&sd)) return("Can't find directory");
  399.     
  400.   if(!(S_IFDIR & sd.st_mode)) return("Not a directory");
  401.     
  402.   sprintf(owner_p,"%s/.OWN%08X"  ,pp->fullp,inet_num);
  403. #else
  404.   if(stat(pp->fullp,&sd)) return("Can't find directory");
  405.   if(!(S_IFDIR & sd.st_mode)) return("Not a directory");
  406.   
  407.   sprintf(owner_p,"%s/.OWN.%08X"  ,pp->fullp,inet_num);
  408. #endif
  409.   sprintf(list_p,"%s/.FSP_CONTENT",pp->fullp);
  410.   sprintf(private_p,"%s/.FSP_PRIVATE", pp->fullp);
  411.     
  412.   if(!fexist(owner_p) && fexist(private_p))
  413.     return("This directory is private");
  414.     
  415.   if(fsp_content_exists = !FSP_STAT(list_p,&sf)) {
  416. #ifdef VMS
  417.     if (!dchanged) { /* VMS doesn't change the modification-date of a
  418.               directory when the contents has been changed */
  419. #else
  420.     if(sf.st_mtime >= sd.st_mtime) {
  421. #endif
  422.       *fp = fopen(list_p,"r");
  423.       if(!*fp) return("Can't read directory listing");
  424.       return((char *)0);
  425.     }
  426.   }
  427.     
  428.   if(!fsp_content_exists && always_use_cache_dir)
  429.     return(server_get_dir_2(pp,fp,&sd));
  430.     
  431. #ifdef VMS
  432.   unlink(list_p); /* remove old .FSP_CONTENT first (otherwise new file) */
  433. #endif
  434.     
  435.   if(!(*fp = fopen(list_p,"w+"))) {
  436.     if(!fsp_content_exists && !always_use_cache_dir)
  437.       return(server_get_dir_2(pp,fp,&sd));
  438.     return("directory unreadable");
  439.   }
  440.   if(chdir(pp->fullp)) return("Can't cd to directory");
  441.     
  442.   build_dir_file(*fp);
  443.   if(chdir(home_dir) == -1) {
  444.     perror("chdir2");
  445.     exit(1);
  446.   }
  447. #ifdef VMS
  448.   dchanged=0;  /* .fsp_content now up to date */
  449. #endif
  450.   return(NULLP);
  451. }
  452.  
  453. static int fold_path PROTO1(PPATH *, pp)
  454. {
  455.   unsigned char *p;
  456.   unsigned long v1, v2;
  457.     
  458.   p = (unsigned char *) pp->f_ptr;
  459.     
  460.   for(v1 = 0; v2 = *p++; ) {
  461.     if(v1 & 0x80000000) 
  462.       v1 = (v1 << 1) ^ v2 ^ 1;
  463.     else 
  464.       v1 = (v1 << 1) ^ v2;
  465.   }
  466.     
  467.   sprintf(pp->f_ptr,"%c%08X",LF_PFX,v1);
  468.   pp->f_len = 9;
  469. }
  470.  
  471. /**********************************************************************/
  472. /* assume path is validated */
  473. char *server_del_file PROTO2(PPATH *, pp, unsigned long, inet_num)
  474. {
  475.   int is_long;
  476.   struct stat sb;
  477.   char ok_del_p[NBSIZE], owner_p[NBSIZE];
  478.     
  479.   if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  480.     
  481.   if(FSP_STAT(pp->fullp,&sb)) return("unlink: file not accessible");
  482.   if(!(S_ISREG(sb.st_mode))) return("unlink: not an ordinary file");
  483.     
  484. #ifdef VMS  /* more than 2 dots not allowed in filenames */
  485.   sprintf(copy_dir( owner_p,pp),"/.OWN%08X"  ,inet_num);
  486. #else
  487.   sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  488. #endif
  489.   strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL"         );
  490.     
  491.   if(!fexist(owner_p) && !fexist(ok_del_p))
  492.     return("no permission for removing this file");
  493.     
  494.   if(unlink(pp->fullp) == -1) return("unlink: cannot unlink");
  495.     
  496.   if(is_long) {
  497.     *pp->f_ptr = LP_PFX;
  498.     unlink(pp->fullp);
  499.   }
  500.     
  501. #ifdef VMS
  502.   server_update_dir(pp,inet_num);  /* update .FSP_CONTENT */
  503. #endif
  504.   return(NULLP);
  505. }
  506.   
  507. /**********************************************************************/
  508.   
  509. char *server_del_dir PROTO2(PPATH *, pp, unsigned long, inet_num)
  510. {
  511.   struct stat sb;
  512.   char list_p[NBSIZE], ok_del_p[NBSIZE], ok_add_p[NBSIZE], owner_p[NBSIZE];
  513.   char private_p[NBSIZE], ok_mkdir_p[NBSIZE];
  514.   int has_ok_del_p, has_ok_add_p, has_private_p, has_mkdir_p;
  515. #ifdef VMS
  516.   char dirname[NBSIZE];
  517.     
  518.   /* Again the kludge for stat() */
  519.   strcpy(dirname,pp->fullp);
  520.   strcat(dirname,".dir.1"); /* for here, add .DIR.1 for directory */
  521.     
  522.   if(FSP_STAT(dirname,&sb)) return("rmdir: directory not accessible");
  523.   if(!(S_ISDIR(sb.st_mode))) return("rmdir: not an ordinary directory");
  524.     
  525.   /* more than 2 dots not allowed in filenames */
  526.   sprintf( owner_p,"%s/.OWN%08X", pp->fullp,inet_num);
  527.     
  528. #else
  529.   if(FSP_STAT(pp->fullp,&sb)) return("rmdir: directory not accessible");
  530.   if(!(S_ISDIR(sb.st_mode))) return("rmdir: not an ordinary directory");
  531.     
  532.   sprintf( owner_p,"%s/.OWN.%08X", pp->fullp,inet_num);
  533. #endif
  534.     
  535.   sprintf(list_p,"%s/.FSP_CONTENT" ,pp->fullp);
  536.   sprintf(ok_del_p,"%s/.FSP_OK_DEL"  ,pp->fullp);
  537.   sprintf(ok_add_p,"%s/.FSP_OK_ADD"  ,pp->fullp);
  538.   sprintf(private_p,"%s/.FSP_PRIVATE" ,pp->fullp);
  539.   sprintf(ok_mkdir_p,"%s/.FSP_OK_MKDIR",pp->fullp         );
  540.     
  541.     
  542.   if(!fexist(owner_p)) return("no permission for removing this directory");
  543.     
  544.   unlink(owner_p); unlink(list_p);
  545.   has_ok_del_p= !unlink(ok_del_p);
  546.   has_ok_add_p = !unlink(ok_add_p);
  547.   has_private_p = !unlink(private_p);
  548.   has_mkdir_p = !unlink(ok_mkdir_p);
  549.     
  550. #ifdef VMS
  551.   if(rmdir(dirname) != 0) {
  552. #else
  553.   if(rmdir(pp->fullp) != 0) {
  554. #endif
  555.     if(has_ok_del_p) touch(ok_del_p);
  556.     if(has_ok_add_p) touch(ok_add_p);
  557.     if(has_private_p) touch(private_p);
  558.     if(has_mkdir_p) touch(ok_mkdir_p);
  559.     if((int) owner_p) touch(owner_p);
  560.     return("rmdir: cannot unlink");
  561.   }
  562.     
  563. #ifdef VMS
  564.   server_update_dir(pp,inet_num); /* update .FSP_CONTENT */
  565. #endif
  566.   return(NULLP);
  567. }
  568.   
  569. /**********************************************************************/
  570.   
  571. char *server_make_dir PROTO2(PPATH *, pp, unsigned long, inet_num)
  572. {
  573.   char ok_add_p[NBSIZE], owner_p[NBSIZE], private_p[NBSIZE];
  574.     
  575. #ifdef VMS /* more than 2 dots not allowed in filenames */
  576.   sprintf(copy_dir( owner_p,pp),"/.OWN%08X"  ,inet_num);
  577. #else
  578.   sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  579. #endif
  580.   strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_MKDIR");
  581.     
  582.   if(!fexist(owner_p) && !fexist(ok_add_p))
  583.     return("no permission for directory creation");
  584.     
  585.   /* make directory and place ownerfile in it */
  586.     
  587. #ifdef VMS
  588.   sprintf(owner_p,  "%s/.OWN%08X",pp->fullp,inet_num);
  589.   if(mkdir(pp->fullp,0) != 0) return("Can't create directory");
  590.   server_update_dir(pp,inet_num); /* update .FSP_CONTENT */
  591. #else
  592.   sprintf(owner_p,"%s/.OWN.%08X",pp->fullp,inet_num);
  593.   if(mkdir(pp->fullp,0777) != 0) return("Can't create directory");
  594. #endif
  595.   strcpy(copy_dir(private_p,pp),"/.FSP_PRIVATE");
  596.   if (fexist(private_p)) {  /* subdir in a private dir is also private */
  597.     sprintf(private_p,"%s/.FSP_PRIVATE",pp->fullp);
  598.     touch(private_p);
  599.   }
  600.   touch(owner_p);
  601.   return(NULLP);
  602. }
  603.   
  604. /**********************************************************************/
  605.   
  606. char *server_get_file PROTO4(PPATH *, pp, FILE **, fp,
  607.                  unsigned long, inet_num,
  608.                  unsigned short, port_num)
  609. {
  610.   struct stat sb;
  611.   char   private_p[NBSIZE], owner_p[NBSIZE];
  612.   FPCACHE *cache_f;
  613. #ifdef VMS
  614. # ifdef MOREDOTS
  615.   char   *dot;
  616. # endif
  617. #endif
  618.     
  619.   if(pp->f_len > max_nlen) fold_path(pp);
  620.     
  621. #ifdef MOREDOTS
  622.   if(FSP_STAT(pp->fullp,&sb)) {
  623.     /* file not found, try without $-conversion (for linked directories) */
  624.     if (dot=strstr(pp->fullp,"$")) *dot++='.'; /* conv. $ back to dot */
  625.     if (FSP_STAT(pp->fullp,&sb)) return("Can't find file");
  626.   }
  627. #else
  628.   if (FSP_STAT(pp->fullp,&sb)) return("Can't find file");
  629. #endif
  630.     
  631.   if(!(S_ISREG(sb.st_mode))) return("Not a file");
  632.     
  633. #ifdef VMS  /* more than one dot not allowed in filenames */
  634.   isvar = isvariable(sb); /* return file format type*/
  635. #endif
  636.   if(!(cache_f = find_cache(fpcache, port_num, inet_num, pp->fullp))) {
  637.     /* file not found in cache? */
  638.     /* clear current cache-entry first */
  639.     if(dbug) printf("get_file: going to delete cache_p: %d\n", cache_p);
  640.     delete_cache(cache_p);
  641. #ifdef VMS
  642.     sprintf(copy_dir(  owner_p,pp),"/.OWN%08X", inet_num);
  643. #else
  644.     sprintf(copy_dir(  owner_p,pp),"/.OWN.%08X", inet_num);
  645. #endif
  646.     strcpy(copy_dir(private_p,pp),"/.FSP_PRIVATE"       );
  647.     
  648.     if(!fexist(owner_p) && fexist(private_p))
  649.       return("no permission for reading this file");
  650.     
  651.     if(fexist(private_p)) {
  652.       /* if(!pp->passwd[0]) return("You need an FSP_PASSWORD"); */
  653.       if(server_check_pass(owner_p, pp->passwd))
  654.     return("Invalid FSP_PASSWORD");
  655.     }
  656.     
  657.     /* open new file */
  658.     if(!(*fp = fopen(pp->fullp,"r"))) return("Can't open file");
  659.     
  660.     /* add it to the file-cache */
  661.     cache_p = add_cache(fpcache,cache_p,port_num,inet_num,pp->fullp,*fp);
  662.   } else *fp = cache_f->fp; /* get filepoint from cache */
  663.     
  664.   return(NULLP);
  665. }
  666.   
  667. /**********************************************************************/
  668. /* result and pp->fullp may overlap */
  669. char *server_get_pro PROTO3(PPATH *, pp, char *, result,
  670.                 unsigned long, inet_num)
  671. {
  672.   struct stat sb;
  673.   FILE *readme;
  674.   char buf[NBSIZE], proflags=0;
  675.   char buf1[UBUF_SPACE];
  676.   unsigned len, num;
  677. #ifdef VMS
  678.   char dirname[NBSIZE];
  679.     
  680.   /* And again the kludge with the dirname conversion for stat() */
  681.   if (*pp->fullp=='.') getcwd(dirname,512,0);
  682.   else strcpy(dirname,pp->fullp);
  683.   strcat(dirname,".dir.1"); /* for here, add .DIR.1 for directory */
  684.     
  685.   if(FSP_STAT(dirname,&sb)) return("getpro: directory not accessible");
  686.   if(!(S_ISDIR(sb.st_mode))) return("getpro: not an ordinary directory");
  687.     
  688.   sprintf(buf,"%s/.OWN%08X",pp->fullp,inet_num);
  689. #else
  690.   if(FSP_STAT(pp->fullp,&sb)) return("getpro: directory not accessible");
  691.   if(!(S_ISDIR(sb.st_mode))) return("getpro: not an ordinary directory");
  692.     
  693.   sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  694. #endif
  695.     
  696.   if(fexist(buf)) proflags |= DIR_OWNER;
  697.   sprintf(buf,"%s/.FSP_OK_DEL"   ,pp->fullp);
  698.   if(fexist(buf)) proflags |= DIR_DEL;
  699.   sprintf(buf,"%s/.FSP_OK_ADD"   ,pp->fullp);
  700.   if(fexist(buf)) proflags |= DIR_ADD;
  701.   sprintf(buf,"%s/.FSP_PRIVATE"  ,pp->fullp);
  702.   if(fexist(buf)) proflags |= DIR_PRIV;
  703.   sprintf(buf,"%s/.FSP_OK_MKDIR" ,pp->fullp);
  704.   if(fexist(buf)) proflags |= DIR_MKDIR;
  705.     
  706.   sprintf(buf,"%s/%s", pp->fullp, readme_file);
  707.     
  708.   sprintf(result, "\n");
  709.     
  710.   len = strlen(result);
  711.   /* the README file is opened with fopen() -- probably not necessary */
  712.   if((readme = fopen(buf,"r")) != 0) {
  713.     proflags |= DIR_README;
  714.     /* Note, this number might have to be hand tweaked later. */
  715.     num = fread(buf1, sizeof(char), UBUF_SPACE-len, readme);
  716.     buf1[num] = '\0';
  717.     fclose(readme);
  718.     strcat(result, buf1);
  719.   }
  720.   result[strlen(result)] = '\0';
  721.   result[strlen(result)+1] = proflags;
  722.   return(NULLP);
  723. }
  724.   
  725. /**********************************************************************/
  726.  
  727. char *server_set_pro PROTO3(PPATH *, pp, char *, key, unsigned long, inet_num)
  728. {
  729.   struct stat sb;
  730.   char buf[NBSIZE];
  731. #ifdef VMS
  732.   char dirname[NBSIZE];
  733.     
  734.   /* And again the kludge with the dirname conversion for stat() */
  735.   if (*pp->fullp=='.') getcwd(dirname,512,0);
  736.   else strcpy(dirname,pp->fullp);
  737.   strcat(dirname,".dir.1"); /* for here, add .DIR.1 for directory */
  738.     
  739.   if(FSP_STAT(dirname,&sb)) return("getpro: directory not accessible");
  740.   if(!(S_ISDIR(sb.st_mode))) return("getpro: not an ordinary directory");
  741.     
  742.   sprintf(buf,"%s/.OWN%08X",pp->fullp,inet_num);
  743. #else
  744.   if(FSP_STAT(pp->fullp,&sb)) return("getpro: directory not accessible");
  745.   if(!(S_ISDIR(sb.st_mode))) return("getpro: not an ordinary directory");
  746.     
  747.   sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  748. #endif
  749.   if(!fexist(buf)) return("no permission for changing the protection-mode");
  750.     
  751.   switch(key[1]) {
  752.     case 'c':
  753.       sprintf(buf,"%s/.FSP_OK_ADD"  ,pp->fullp);
  754.       break;
  755.     case 'd':
  756.       sprintf(buf,"%s/.FSP_OK_DEL"  ,pp->fullp);
  757.       break;
  758.     case 'p':
  759.       sprintf(buf,"%s/.FSP_PRIVATE" ,pp->fullp);
  760.       break;
  761.     case 'm':
  762.       sprintf(buf,"%s/.FSP_OK_MKDIR",pp->fullp);
  763.       break;
  764.     default:
  765.       return("bad flag");
  766.   }
  767.     
  768.   switch(key[0]) {
  769.     case '+':
  770.       touch(buf);
  771.       break;
  772.     case '-':
  773.       unlink(buf);
  774.       break;
  775.     default:
  776.       return("bad flag");
  777.     }
  778.     
  779.   return(NULLP);
  780. }
  781.   
  782. /**********************************************************************
  783.  *  These two are used for file uploading.
  784.  **********************************************************************/
  785.   
  786. char *server_up_load PROTO5(char *, data, int, len, unsigned long, pos,
  787.                 unsigned long, inet_num, unsigned short, port_num)
  788. {
  789.   FILE *fp;
  790.   char  tname[NBSIZE];
  791.   FPCACHE *cache_f;
  792.  
  793. #ifdef VMS  /* dir_cache_dir is already in VMS format */
  794.   if(always_use_cache_dir)
  795.     sprintf(tname,"%sT%08X%04X",dir_cache_dir,inet_num,port_num);
  796.   else
  797.     sprintf(tname,"T%08X%04X", inet_num, port_num);
  798. #else
  799.   if(always_use_cache_dir)
  800.     sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  801.   else
  802.     sprintf(tname, ".T%08X%04X", inet_num, port_num);
  803. #endif
  804.     
  805.   if(!(cache_f = find_cache(fpcache, port_num, inet_num, tname))) {
  806.     /* file not found in cache? */
  807.     /* clear out current cache-entry first */
  808.     delete_cache(cache_p);
  809.     if (pos) {
  810.       if(fp = fopen(tname, "r+")) fseek(fp, pos, 0);
  811.     } else {
  812.       unlink(tname);
  813.       fp = fopen(tname,"w");
  814.     }
  815.     
  816.     if(!fp) return("Cannot open temporary file");
  817.     
  818.     fwrite(data, 1, len, fp);
  819.     /* add it to the file cache */
  820.     cache_p = add_cache(fpcache,cache_p,port_num,inet_num,tname,fp);
  821.   } else { /* file found in cache, using cache-fp */
  822.     fp = cache_f->fp;
  823.     if(pos!=ftell(fp)) fseek(fp, pos, 0);
  824.     fwrite(data, 1, len, fp);
  825.   }
  826.   return(NULLP);
  827. }
  828.   
  829. char *server_install PROTO3(PPATH *, pp, unsigned long, inet_num,
  830.                 unsigned short, port_num)
  831. {
  832.   FILE *ft, *fp;
  833.   char tname[NBSIZE],  owner_p[NBSIZE], save_p[NBSIZE], buf[512];
  834.   char ok_del_p[NBSIZE], ok_add_p[NBSIZE];
  835.   int bytes, is_long;
  836.   FPCACHE *cache_f;
  837. #ifdef VMS
  838.   char filename[NBSIZE];
  839. # ifdef MOREDOTS
  840.   char *dot; /* pointer to a dot in a filename */
  841. # endif
  842. #endif
  843.     
  844.   if(is_long = (pp->f_len > max_nlen)) {
  845.     strcpy(save_p,pp->f_ptr);
  846.     fold_path(pp);
  847.   }
  848.     
  849. #ifdef VMS
  850.   sprintf(copy_dir(owner_p,pp),"/.OWN%08X",inet_num);
  851.   sprintf(tname,"%sT%08X%04X",dir_cache_dir,inet_num,port_num);
  852. #else
  853.   sprintf(copy_dir(owner_p,pp),"/.OWN.%08X",inet_num);
  854.   sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  855. #endif
  856.   /* if file still in cache, then close it & remove it from cache */
  857.   if(cache_f = find_cache(fpcache,port_num, inet_num, tname))
  858.     delete_cache(cache_f);
  859.     
  860. #ifdef MOREDOTS
  861.   while (dot=strstr(pp->fullp,".")) *dot++='$'; /* replace dots with '$' */
  862. #endif
  863.   if (dbug)
  864.     printf("server_install: owner_p: %s, tname: %s, pp->fullp: %s\n", owner_p,
  865.        tname, pp->fullp);
  866.   if(!fexist(owner_p)) {
  867.     strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_ADD");
  868.     strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL");
  869.     
  870.     if(!fexist(ok_add_p)) {
  871.       unlink(tname);
  872.       return("no permission for creating that file");
  873.     }
  874.     
  875.     if(!fexist(ok_del_p) && fexist(pp->fullp)) {
  876.       unlink(tname);
  877.       return("no permission for replacing that file");
  878.     }
  879.   }
  880.     
  881.   unlink(pp->fullp);
  882.   if(link(tname,pp->fullp) == 0) {
  883.     unlink(tname);
  884.     goto done;
  885.   }
  886.     
  887.   /* link failed, so just copy the temp file */
  888.   if(!(ft = fopen(tname,"r"))) {
  889.     unlink(tname);
  890.     return("Can't open temporary file");
  891.   }
  892.     
  893.   if(!(fp = fopen(pp->fullp,"w"))) {
  894.     unlink(tname);
  895.     fclose(ft);
  896.     return("Can't open file for output");
  897.   }
  898.   /* copy temporary file to actual fput file */
  899.   while(bytes = fread(buf,1,sizeof(buf),ft)) fwrite(buf,1,bytes,fp);
  900.     
  901.   fclose(ft); fclose(fp); unlink(tname);
  902.     
  903.  done:
  904.     
  905.   if(is_long) {
  906.     *pp->f_ptr = LP_PFX;
  907.     if(!(fp = fopen(pp->fullp,"w"))) {
  908.       *pp->f_ptr = LF_PFX;
  909.       unlink(tname);
  910.       return("Can't create long named file for output");
  911.     }
  912.     fputs(save_p,fp); fclose(fp);
  913.   }
  914.     
  915. #ifdef VMS
  916.   server_update_dir(pp,inet_num); /* update .FSP_CONTENT */
  917. #endif
  918.   return(NULLP);
  919. }
  920.   
  921. /**********************************************************************/
  922. /* assume path is validated */
  923. char *server_secure_file PROTO3(PPATH *, pp, unsigned long, inet_num,
  924.                 unsigned short, port_num)
  925. {
  926.   int is_long;
  927.   struct stat sb;
  928.   char ok_del_p[NBSIZE], owner_p[NBSIZE], temp_p[NBSIZE];
  929.   char private_p[NBSIZE];
  930.     
  931.   if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  932.   if(FSP_STAT(pp->fullp,&sb)) return("grab: file not accessible");
  933.   if(!(S_ISREG(sb.st_mode))) return("grab: not an ordinary file");
  934.     
  935. #ifdef VMS /* more than one dot not allowed */
  936.   sprintf(copy_dir( owner_p,pp),"/.OWN%08X", inet_num);
  937. #else
  938.   sprintf(copy_dir( owner_p,pp),"/.OWN.%08X", inet_num);
  939. #endif
  940.   strcpy(copy_dir( ok_del_p,pp),"/.FSP_OK_DEL");
  941.   strcpy(copy_dir(private_p,pp),"/.FSP_PRIVATE");
  942.   sprintf(copy_dir(   temp_p,pp),"/.G%08X%04X", inet_num,port_num);
  943.     
  944.   if(!fexist(owner_p) && (!fexist(ok_del_p) || fexist(private_p)))
  945.     return("grab: no permission for grabbing this file");
  946.     
  947.   if (fexist(private_p)) {
  948.     /* if (!pp->passwd[0]) return("You need an FSP_PASSWORD"); */
  949.     if (server_check_pass(owner_p,pp->passwd))
  950.       return("Invalid FSP_PASSWORD");
  951.   }
  952.     
  953.   unlink(temp_p);
  954.   /* link on VMS emulated as a filecopy */
  955.   if(link(pp->fullp,temp_p) == -1) return("grab: cannot make link");
  956.   if(unlink(pp->fullp) == -1) {
  957.     unlink(temp_p);
  958.     return("grab: cannot unlink");
  959.   }
  960.     
  961.   if(is_long) {
  962.     *pp->f_ptr = LP_PFX;
  963.     unlink(pp->fullp);
  964.   }
  965.     
  966.   return(NULLP);
  967. }
  968.   
  969. char *server_grab_file PROTO4(PPATH *, pp, FILE **, fp,
  970.                   unsigned long, inet_num,
  971.                   unsigned short, port_num)
  972. {
  973.   struct stat sb;
  974.   char temp_p[NBSIZE];
  975.     
  976.   sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  977.     
  978.   if(FSP_STAT(temp_p,&sb)) return("grab: can't find file");
  979.   if(!(S_ISREG(sb.st_mode))) return("grab: Not a file");
  980.   if(!(*fp = fopen(temp_p,"r"))) return("grab: can't open file");
  981.   return(NULLP);
  982. }
  983.   
  984. char *server_grab_done PROTO3(PPATH *, pp, unsigned long, inet_num,
  985.                   unsigned short, port_num)
  986. {
  987.   struct stat sb;
  988.   char temp_p[NBSIZE];
  989.     
  990.   sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  991.   if(FSP_STAT(temp_p,&sb)) return("grab: can't find temporary file");
  992.   if(unlink(temp_p) == -1) return("grab: can't delete temporary file");
  993. #ifdef VMS
  994.   server_update_dir(pp,inet_num); /* update .FSP_CONTENT */
  995. #endif
  996.   return(NULLP);
  997. }
  998.   
  999. /**********************************************************************/
  1000.   
  1001. /**********************************************************************/
  1002.   
  1003. void init_home_dir PROTO0((void))
  1004. {
  1005. #ifndef VMS
  1006.   if(*home_dir != '/') { 
  1007.     fprintf(stderr,"[%s] does not start with a /\n", home_dir);
  1008.     exit(1); 
  1009.   }
  1010. #endif
  1011. /* test and goto home dir */
  1012.   if(chdir(home_dir) == -1) {
  1013.     perror(home_dir);
  1014.     exit(1);
  1015.   }
  1016.  
  1017. /* test cache dir */
  1018.   if(always_use_cache_dir && (chdir(dir_cache_dir) == -1)) {
  1019.     perror(dir_cache_dir);
  1020.     exit(1);
  1021.   }
  1022.  
  1023. /* go back to home_dir */
  1024.   if(chdir(home_dir) == -1) {
  1025.     perror(home_dir);
  1026.     exit(1);
  1027.   }
  1028.  
  1029.   if(dbug) {
  1030.     fprintf(stderr,"home on %s\n",home_dir);
  1031.     if(always_use_cache_dir)
  1032.       fprintf(stderr,"cache on %s\n", dir_cache_dir);
  1033.     fflush(stderr);
  1034.   }
  1035. }
  1036.